package win.larryzeal.spring.web.controller;

import org.springframework.http.CacheControl;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;
import win.larryzeal.spring.entity.Book;

import java.time.Instant;
import java.util.concurrent.TimeUnit;

/**
 * 测试Spring MVC对HTTP cache的支持。
 * eTag，就是服务器返回一个eTag，然后浏览器下次访问相同URL的时候携带上这个eTag，看看是否发生了更改。
 * 如果没有更改，那服务器直接返回304，那浏览器使用缓存即可。
 * 否则，使用新值。
 * <p>
 * Created by 张少昆 on 2017/9/14.
 */
@Controller
@RequestMapping( "/book" )
public class BookController {

	/**
	 * 本方法是使用ResponseEntity，让SpringMVC帮助处理。
	 * <p>
	 * 根据id查找书本。找到之后，会将book自带的version放入eTag中，以便让浏览器缓存。
	 * 注意，本方法，这样做，不仅会在response中带有ETag和Cache-Control headers，还会 将response转换成 一个响应体为空的HTTP 304 Not Modified response -- 如果客户端发送的conditional headers 匹配Controller设置的caching information。
	 *
	 * @param id 书本id
	 * @return http entity
	 */
	@GetMapping( "/{id}" )
	public ResponseEntity<Book> showBook(@PathVariable Long id){

		Book book = findBook(id);
		String version = book.getVersion(); //不一定要用这个，也可以用MD5什么的生成。

		return ResponseEntity
				.ok()
				.cacheControl(CacheControl.maxAge(30, TimeUnit.DAYS)) //注意，这里不是Cookie，是Cache，囧
				.eTag(version) // lastModified is also available
				.body(book);
	}

	//	private final String now=Instant.now().toString(); //不能总变，不能一直不变，都不利于测试！
	private int counter = 0;

	/**
	 * 模拟方法
	 *
	 * @param id
	 * @return
	 */
	private Book findBook(Long id){
		counter++;
		boolean flag = true;
		if(counter % 3 == 0){ //请求满三次再更改eTag。
			flag = false;
		}
		Book book = new Book();
		book.setId(id);
		book.setVersion(String.valueOf(flag));
		return book;
	}
}
